
#include "Neuron.h"

#include "EvolutionOfBehavior.h"
#include "Creature.h"

namespace jcrada {

    EvolutionOfBehavior::EvolutionOfBehavior( int population_size,
            const Creature& creature ) : EvolutionOfCreatures( population_size ),
    _model( NULL ) {
        for (int i = 0; i < getPopulationSize(); ++i) {
            setCreature(i, creature.clone());
            getCreature(i).setFitness(-1.0 / 0.0);
        }
        PsoParticle* particle = new PsoParticle(
                creature.getNeuralNetwork().getTotalNumberOfWeights());
        particle->setMinPosition(-1.0);
        particle->setMaxPosition(1.0);
        particle->setMaxVelocity(1.0);
        particle->setSpace(PsoParticle::S_CONTINUOUS);
        _model = new PsoModel(population_size, *particle, false);
        delete particle;
    }

    EvolutionOfBehavior::~EvolutionOfBehavior( ) {
        delete _model;
    }

    void EvolutionOfBehavior::step( ) {
        for (int i = 0; i < getPopulationSize(); ++i) {
            getModel().getParticle(i).setFitness(getCreature(i).getFitness());
        }
        getModel().step();
    }

    void EvolutionOfBehavior::prepareCreatures( ) {
        for (int i = 0; i < getModel().getSize(); ++i) {
            PsoParticle& particle = getModel().getParticle(i);
            getCreature(i).reset();
            NeuralNetwork& nn = getCreature(i).getNeuralNetwork();
            int index = 0;
            int layers = nn.getNumberOfLayers();
            for (int j = 1; j < layers; ++j) {
                int neurons = nn.getLayer(j).getNumberOfNeurons();
                for (int k = 0; k < neurons; ++k) {
                    int inputs = nn.getLayer(j).getNeuron(k).getNumberOfInputs();
                    for (int l = 0; l < inputs; l++) {
                        nn.getLayer(j).getNeuron(k).setInput(l, particle.getPosition(index++));
                    }
                    nn.getLayer(j).getNeuron(k).setThreshold(particle.getPosition(index++));
                }
            }
            getCreature(i).set();
        }

    }
}
